package br.com.sig.presentation.action;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.inject.Named;

import org.jboss.seam.international.status.builder.BundleKey;

import br.com.sig.business.exception.BaseException;
import br.com.sig.business.model.entity.BaseEntity;
import br.com.sig.criteria.CriteriaVisitor;
import br.com.sig.presentation.BaseDataModel;

@Named
public abstract class BaseListAction<T extends BaseEntity> extends Action<T> implements Serializable {

	private static final long serialVersionUID = 1854228357978238736L;
	
	private boolean asc = true;
	private String sortField;
	protected CriteriaVisitor visitor = null;
	
	protected List<T> resultList = null;
	private BaseDataModel<T> pagedResult = null;
	private T selectedItem = null;
	private List<T> selections = null;
	
	private BaseAction<T> action = null;
	
	@PostConstruct
	public void baseInit() {
		setOperation(Operation.LIST);
	}
	
	public void reset() {
		clearResult();
		resultList = null;
		getPagedResult().reset();
		getSelections().clear();
		setSelectedItem(null);		
	}
		
	public void find() {		
		reset();		
		if (!hasResult()) {
			messages.warn(new BundleKey("messages", "warn.no.result"));
		}		
	}

	public List<T> createPagedResultList(int first, int pageSize) {
		try {
			return getService().find(getInstance(), getSortField(), isAsc(), first, pageSize, this.visitor);
		} catch (BaseException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public Integer createResultCount() {
		return getService().count(getInstance(), this.visitor);
	}

	public boolean hasResult() {
		return getPagedResult().getRowCount() > 0;
	}
	
	public void clearResult() {
		getPagedResult().getWrappedData().clear();
	}
	
	protected void clearSelections() {
		getSelections().clear();
	}
	
	public boolean hasSelection() {
		return !(getSelections().isEmpty());
	}
	
	public boolean hasMoreThanOneSelection() {
		return hasSelection() && getSelections().size() > 1;
	}	
	
	public boolean isList() {
		return Operation.LIST.equals(getOperation());
	}
	
	public void prepareList(boolean cancel) {
		setOperation(Operation.LIST);
		clearInstance();
		reset();
		getPagedResult().init();
		action.clearOperation();
		if (action.isManaged() && cancel) {
			action.refreshInstance();
		}
		action.clearInstance();		
	}
	
	public void startModal() {
		super.startModal();
		reset();
		getPagedResult().init();
	}
	
	public boolean enableEditOperation() {
		return true;
	}
	
	public boolean enableDeleteOperation() {
		return true;
	}
	
	public String rowStyleClass(T entity) {
		return null;
	}
	
	/*************** GETS e SETS *******************/
	
	public boolean isAsc() {
		return asc;
	}

	public void setAsc(boolean asc) {
		this.asc = asc;
	}

	public String getSortField() {
		return sortField;
	}

	public void setSortField(String sortField) {
		this.sortField = sortField;
	}	
	
	public BaseDataModel<T> getPagedResult() {
		if (this.pagedResult == null) {
			this.pagedResult = new BaseDataModel<T>(this);
		}
		return pagedResult;
	}	

	public List<T> getResultList() {		
		try {
			if (this.resultList == null) {
				if (getSortField() != null) {
					setResultList(getService().findAll(getSortField(), isAsc()));
				} else {
					setResultList(getService().findAll());
				}
			}
		} catch (BaseException e) {
			e.printStackTrace();
			messages.error(new BundleKey("messages", "error.find"));
		}
		return resultList;
	}	
	
	public void setResultList(List<T> resultList) {
		this.resultList = resultList;
	}
	
	public T getSelectedItem() {
		return selectedItem;
	}

	public void setSelectedItem(T selectedItem) {
		this.selectedItem = selectedItem;
	}	
	
	public List<T> getSelections() {
		if (this.selections == null) {
			this.selections = new ArrayList<T>();
		}
		return selections;
	}

	public void setSelections(List<T> selections) {
		this.selections = selections;
		if (!getSelections().isEmpty()) {
			this.setSelectedItem(this.getSelections().get(getSelections().size()-1));
		} else {
			setSelectedItem(null);
		}
	}

	public BaseAction<T> getAction() {
		return action;
	}

	public void setAction(BaseAction<T> action) {
		this.action = action;
	}	
}